package com.jml.springboot流程010;

import com.jml.springboot流程010.controller.IndexController;
import java.io.PrintStream;
import org.springframework.boot.Banner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.autoconfigure.web.servlet.DispatcherServletAutoConfiguration;
import org.springframework.boot.autoconfigure.web.servlet.ServletWebServerFactoryAutoConfiguration;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.core.env.Environment;


@SpringBootApplication
public class AppJml {
    public static void main(String [] args) {
        
        /*
        springboot容器启动成功后就会返回当前容器的上下文
        SpringApplication.run(Object.class); 等价于(new SpringApplication(primarySources)).run(args);
        * */
        
        /*
        ConfigurableApplicationContext applicationContext = SpringApplication.run(AppJml.class);
        */
        
        /*
        ConfigurableApplicationContext applicationContext = new SpringApplication(AppJml.class).run(args);
       */
        
        //创建springApplication
        //1.先初始化项目启动类型，根据WebApplicationType决定是servlet还是响应式容器还是NONE
    
        //2.setInitializers((Collection) getSpringFactoriesInstances(ApplicationContextInitializer.class));
        //result = (Collection) getSpringFactoriesInstances(ApplicationContextInitializer.class)
        //在spring的META-INF/spring.factories中有没有ApplicationContextInitializer这个类型，把这个类型下的value加载到IOC容器中
    
        //3.setListeners((Collection) getSpringFactoriesInstances(ApplicationListener.class));
        //(Collection) getSpringFactoriesInstances(ApplicationListener.class)
        //在spring的META-INF/spring.factories中有没有ApplicationListener这个类型，把这个类型下的value加载到IOC容器中
        //初始化当前的主类，就是启动类
        SpringApplication springApplication = new SpringApplication(AppJml.class);
        
        //4.SpringApplicationRunListeners listeners = getRunListeners(args);读取配置文件把配置文件读入到容器中
        //      读取MATE-INF/spring.factories中de key是SpringApplicationRunListeners，
        //      value是EventPublishingRunListener。
        //      这个类的作用是给springboot配置文件进行赋值。读取自定义的配置文件my.properties
        //      SpringApplicationRunListeners有一个List容器，存的是SpringApplicationRunListener接口的实现类
        //5.listeners.starting();遍历List容器的start，用的监听者模式
        
        //6.对参数环境进行赋值ConfigurableEnvironment environment = prepareEnvironment(listeners,applicationArguments);
        //      最后会通过循环调用所有的SpringApplicationRunListener接口的实现类的environmentPrepared方法，
        //      这个方法就是读取配置文件到容器中。
    
    
    
        //7.run方法中打印banner图，在这里可以自定义打印的Banner图
        //springApplication.setBanner (new Banner() {
        //    @Override
        //    public void printBanner(Environment environment, Class<?> sourceClass,
        //            PrintStream out) {
        //       System.out.println("打印自定义banner，代替spring的banner");
        //    }
        //});
    
        //8.@SpringBootApplication注解在方法refreshContext(context)中生效
        // 先创建tomcat在初始化DispatchServlet。然后加载springmvc。
        // 在注解注解@SpringBootApplication中的@EnableAutoConfiguration，实例化类AutoConfigurationImportSelector
        //读取MATE-INF/spring.factories中的value，第三方的配置类把全限定类名放入List，根据引用的jar包最后把这相应的类放入容器中。
        //实例化的类有一个是ServletWebServerFactoryAutoConfiguration，
        //      在这个类中的serverProperties就是配置服务器的信息，比如server.port=8080
        //      在这个类的@Import()中的三个类加载了三个容器
        //      springboot支持三种Tomcat，Jetty.class,Undertow 默认是tomcat，
        //实例化的类有一个是DispatcherServletAutoConfiguration
        //      在他的内部类DispatcherServletConfiguration中会初始化DispatchServlet类放入容器，
        //      内部类有一个属性WebMvcProperties，这个类 就会接受springmvc在yml文件的配置。同serverProperties一样
        
        
        
        
        
        
        
        //调用run方法启动
        //springboot启动：1.加载注解方式的springmvc  2.加载tomcat
        ConfigurableApplicationContext applicationContext = springApplication.run(args);
        String[] beanDefinitionNames = applicationContext.getBeanDefinitionNames();
        for(int i=0;i<beanDefinitionNames.length;i++){
            System.out.println("bean的名称"+beanDefinitionNames[i]);
        }
        
        
        IndexController indexController = applicationContext.getBean("indexController", IndexController.class);
        System.out.println(indexController);
    }
}
